#include "log.h"
#include "pipe.h"
#include "ShareMgr.h"
#include "ShareTransport.h"

#define ARG_COUNT 2

constexpr size_t MAX_SIZE = 1024 * 1024 * 5;
constexpr size_t BACKUP_FILES = 1;
const std::string LOG_FILE = "C:\\ProgramData\\VMGT\\log\\vmgt.log";

void WaitRunning(PipeClient* client, ShareMgr* shMgr)
{
    LOGI("Share Manager is running");
    if (!client) {
        LOGI("PipeClient is NOT set");
        WaitForSingleObject(shMgr->GetWaitHandle(), INFINITE);
    } else {
        LOGI("PipeClient is set");
        HANDLE hWaitObj[] = {shMgr->GetWaitHandle(), client->GetHandle()};
        // 2 Indicates the size of hWaitObj.
        WaitForMultipleObjects(2, hWaitObj, FALSE, INFINITE);
    }
}

int wmain(ULONG argc, PWCHAR argv[])
{
    try {
        Log::Instance().Init(LOG_FILE, MAX_SIZE, BACKUP_FILES);
    } catch (const LogException&) {
        return 0;
    }

    LOGI("vmgtsharemgr.exe built on {} {}", __DATE__, __TIME__);
    PipeClient* pClient = nullptr;

    do {
        if (argc == ARG_COUNT && iswdigit(argv[1][0])) {
            std::wstring pipename = VMGTSHARE_PIPE_NAME;
            pipename.append(argv[1]);
            pClient = new PipeClient(pipename);
            if (!pClient) {
                LOGE("Failed to new PipeClient");
                break;
            }

            if (!pClient->Init()) {
                LOGE("Failed to init PipeClient");
                break;
            }
            LOGI("PipeClient Init Completed");
        }

        /* Sets shutdown parameters for the currently calling process.
        * This function sets a shutdown order for a process relative
        * to the other processes in the system.
        */
        SetProcessShutdownParameters(0x100, 0);

        ShareMgr shMgr;
        if (shMgr.InitShareMgrWindow()) {
            LOGE("Failed to init Share manager window");
            break;
        }

        DWORD ret = shMgr.InitShareMgrConfig();
        if (ret == ERROR_SUCCESS) {
            LOGI("Share manager configuration init completed");
        } else if (ret == ERROR_CONNECTION_INVALID) {
            LOGE("Failed to connect vioserial device");
        } else if (ret == ERROR_ALREADY_INITIALIZED) {
            LOGW("Share manager Configuration already initialised");
        } else {
            LOGE("Failed to init Share manager configuration: {}", ret);
            break;
        }

        WaitRunning(pClient, &shMgr);
    } while (0);

    if (pClient) {
        pClient->Close();
        delete pClient;
        pClient = nullptr;
    }

    return 0;
}
